<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<template>
  <div class="chat-page">
    <div class="chat-section">
      <div class="chat-left">
        <div v-if="tempUser" class="chat-room">
          <!-- 名称 -->
          <div class="room-top">
            <el-button type="danger" icon="el-icon-close" circle size="small" @click="closeRoomClick" />
            <div class="name">{{ tempUser.type === 1 ? tempUser.username : tempUser.name }}</div>
            <i v-if="tempUser.type === 2" class="el-icon-circle-plus-outline group-plus" @click="groupAddMemberClick" />
          </div>
          <!-- 消息列表展示 -->
          <div id="scroll-page" class="room-content">
            <div v-if="isLoadingMsg" style="text-align: center;color: #999;font-size: 15px;">正在加载。。。</div>
            <div v-if="tempUser.type === 1">
              <div v-for="(item, index) in msgDataSource[tempUser.user_id].msgList" :key="item.unique_id" class="msgrow"
                :data-index="index" :data-msgid="item.message_id">
                <div v-if="item.sender_id === userId" class="message msg-center msg-right">
                  <!-- <自己发送的> -->
                  <div v-if="item.message_type === 'TEXT'" class="talk-pop">{{ item.content }}</div>
                  <div v-else-if="item.message_type === 'IMG'">
                    <el-image class="msg-img" :src="item.content" @load="e => imgLoaded(e, item)" />
                  </div>
                  <div v-loading="item.status == 'sending'" element-loading-spinner="el-icon-loading"
                    element-loading-background="rgba(0,0,0,0)" class="state">
                    <span v-if="item.status === 'sending'">发送中</span>
                    <span v-else-if="item.status === 'failed'" @click="sendAgainClick(item)">发送失败</span>
                    <span v-else-if="item.status === 'Sent'">已发送</span>
                    <span v-else-if="item.status === 'Read'">已读</span>
                    <span v-else-if="item.status === 'Received'">未读</span>
                    <span v-else>其它</span>
                  </div>
                </div>
                <div v-else class="message msg-center msg-left">
                  <!-- <别人发送的> -->
                  <div v-if="item.message_type === 'TEXT'" class="talk-pop">{{ item.content }}</div>
                  <div v-else-if="item.message_type === 'IMG'">
                    <el-image class="msg-img" :src="item.content" @load="e => imgLoaded(e, item)" />
                  </div>
                  <div class="state">
                    <span v-if="item.status === 'Read'">已读</span>
                    <span v-else>未读</span>
                  </div>
                </div>
              </div>
            </div>
            <div v-else-if="tempUser.type === 2">
              <!-- 群消息展示 -->
              <div v-for="(item, index) in groupMsgList[tempUser.id].msgList" :key="item.unique_id" class="msgrow"
                :data-index="index" :data-msgid="item.message_id">
                <div v-if="item.sender_id === userId" class="message group-msg-right msg-right">
                  <div class="sender_name">{{ item.sender_name }}</div>
                  <div v-if="item.message_type === 'TEXT'" class="talk-pop">{{ item.content }}
                    <div class="msg-time">{{ item.sent_at_str }}</div>
                  </div>
                  <div v-else-if="item.message_type === 'IMG'">
                    <el-image class="msg-img" :src="item.content" @load="e => imgLoaded(e, item)" />
                  </div>
                </div>
                <div v-else class="message group-msg-left msg-left">
                  <div class="sender_name">{{ item.sender_name }}</div>
                  <div v-if="item.message_type === 'TEXT'" class="talk-pop">{{ item.content }}
                    <div class="msg-time">{{ item.sent_at_str }}</div>
                  </div>
                  <div v-else-if="item.message_type === 'IMG'">
                    <el-image class="msg-img" :src="item.content" @load="e => imgLoaded(e, item)" />
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 发送消息框 -->
          <!-- <div class="room-send">
              <el-input v-model="tempUser.newMsg" @keyup.enter.native="sendClick" />
              <el-divider direction="vertical" />
              <el-button type="primary" @click="sendClick">发送</el-button>
            </div> -->
          <div class="room-send">
            <FileUpload class="send-input" @send="sendAction" />
            <!-- <el-divider direction="vertical" /> -->
            <!-- <el-button type="primary" @click="sendClick">发送</el-button> -->
          </div>
        </div>
      </div>
      <!-- 右侧列表 -->
      <div class="user-list">
        <el-button @click="createGroupTap">创建群组</el-button>
        <!-- 群列表 -->
        <div v-for="(item, index) in groupList" :key="'g' + index" class="user-item">
          <div class="group-item">
            <el-button class="name" :type="''" link @click="clickToGroupTalk(item, index)">
              <div v-if="item.unRead === true" class="unRead" />
              <span>{{ item.name }}</span>
            </el-button>
            <i :class="[item.isExpand ? 'el-icon-caret-top' : 'el-icon-caret-bottom', 'expand']"
              @click="groupExpandClick(item)" />
          </div>
          <div v-for="(user, row) in item.user_list" v-if="item.isExpand" :key="row" class="group-sub-user">
            <span>{{ user.username }}</span>
          </div>
        </div>
        <!-- 好友列表 -->
        <div v-for="(item, index) in userList" :key="index" class="user-item">
          <el-button class="name" :type="''" link @click="clickToTalk(item, index)">
            <div v-if="item.unRead === true" class="unRead" />
            <span>{{ item.username }}</span>
            <span style="color:#000;font-size:10px;">{{ item.status == 1 ? ' (在线)' : '' }}</span>
          </el-button>
        </div>
      </div>
    </div>

    <!-- 添加群成员窗口 -->
    <el-dialog title="添加群成员" :visible.sync="GroupMemberPlusVisible" class="group-dialog">
      <div v-if="notInGroupUserList.length > 0">
        <el-checkbox v-for="(item, index) in notInGroupUserList" :key="index" :label="item.user_id" class="group-check"
          @change="e => checkMemberChanged(e, item)">{{ item.username }}</el-checkbox>
      </div>
      <div v-else>已经全部在群里了</div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="GroupMemberPlusVisible = false">取消</el-button>
        <el-button type="primary" @click="groupMemberSubmit">邀请（{{ notInGroupCheckList.length }}）</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getMessageList,
  getWsUserList,
  getChatGroupList,
  getGroupMsgList,
  getNotInGroupUserList,
  joinGroupMembers,
  createNewGroup,
  findGroupUserListById
} from '@/api/chat'
import { dateStrFromTimeStamp } from '@/utils/timeformat'
import { decryptMsg } from '@/utils/decrypt'
import FileUpload from './components/fileupload.vue'

import { useUserStoreHook } from "@/store/modules/user"

import {
  sendUserMessage,
  sendGroupMessage,
  sendUserImageMsg,
  sendGroupImageMsg,
  sendFailedMessageAgain,
  receivedMessage,
  readMessage,
} from "@/utils/websocket"

const { user_id, user_name } = useUserStoreHook()

export default {
  components: {
    FileUpload
  },
  data() {
    return {
      toId: '',
      msgText: '',
      groupList: [], // 群组列表
      userList: [], // 好友列表
      tempUser: null, // 临时聊天对象数据
      tempIndex: -1, // 聊天对象在列表中的位置下标
      // id:list
      msgDataSource: {}, // 所有聊天信息 好友的（单对单）
      groupMsgList: {}, // 所有聊天信息 群组的
      // 监听的元素 已经显示在窗口的 下标 位置 列表（按照顺序的）
      observeList: [],
      // 是否正在加载。。。聊天记录
      isLoadingMsg: false,
      // 是否有更多历史记录数据
      hasMore: true,

      GroupMemberPlusVisible: false, // 添加群成员窗口
      notInGroupUserList: [], // 不在群里的用户列表
      notInGroupCheckList: [], // 选中项
      // 需要等待加载的图片个数
      needNexTickCount: 0,
      // 是否需要图片加载结束后 滚动到底部
      needNexTick: false
    }
  },
  computed: {

  },
  watch: {
    msgDataSource() {
      console.log('收到监听')
      if (!this.tempUser) {
        return
      }
      console.log(this.msgDataSource[this.tempUser.user_id].msgList.length)
    }
  },
  mounted() {
    // 监听 消息-消息状态-别人上线-消息发送失败
    window.addEventListener('onmessageWS', this.getSocketMessage)
    window.addEventListener('onmessageGroupWS', this.getSocketGroupMessage)
    window.addEventListener('getSocketMessageStatusChange', this.getSocketMessageStatusChange)
    window.addEventListener('onmessageOtherOnline', this.getOtherOnline)
    // 被拉入新群通知
    window.addEventListener('joinedNewGroupWS', this.joinedNewGroupNoti)
    window.addEventListener('onmessageWSFailed', this.getSendFailedMessage)
  },
  destroyed() {
    window.removeEventListener('onmessageWS', this.getSocketMessage)
    window.removeEventListener('onmessageOtherOnline', this.getOtherOnline)
    window.removeEventListener('onmessageWSFailed', this.getSendFailedMessage)
  },
  created() {
    this.userId = user_id
    console.log(`lll ${user_id}`)
    this.fetchUserList()
    this.fetchGroupList()
  },
  methods: {
    // 点击创建群组
    createGroupTap() {
      this.$prompt('请输入群名称', '创建群组', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPattern: /^(?=.*\S).+$/,
        inputErrorMessage: '请输入群名称'
      }).then(({ value }) => {
        return createNewGroup({
          name: value
        })
      }).then((val) => {
        this.$message.success('创建成功')
        // 后面的 在 收到 被拉入群消息 时 处理 ---
      }).catch(() => {
        console.log('取消')
      })
    },
    // 群组展开点击
    groupExpandClick(item) {
      item.isExpand = !item.isExpand
    },

    // 群组添加成员点击
    groupAddMemberClick() {
      if (this.tempUser && this.tempUser.type === 2) {
        this.notInGroupCheckList = []
        this.fetchNotInGroupUserList(this.tempUser.id)
        this.GroupMemberPlusVisible = true
      }
    },
    // 选中改变方法
    checkMemberChanged(e, item) {
      if (e) {
        this.notInGroupCheckList.push(item)
      } else {
        const index = this.notInGroupCheckList.findIndex(val => val.user_id === item.user_id)
        if (index >= 0) {
          this.notInGroupCheckList.splice(index, 1)
        }
      }
      console.log(this.notInGroupCheckList)
    },

    // 提交邀请。。
    groupMemberSubmit() {
      if (this.notInGroupCheckList.length === 0) {
        return
      }
      const ids = this.notInGroupCheckList.map(val => val.user_id)
      joinGroupMembers({
        group_id: this.tempUser.id,
        ids: ids
      }).then(val => {
        console.log(val)
        this.$message.success('邀请成功')

        const groupIndex = this.groupList.findIndex(val => val.id === this.tempUser.id)
        const groupItem = this.groupList[groupIndex]

        groupItem.user_list = groupItem.user_list.concat(this.notInGroupCheckList)

        this.notInGroupCheckList.forEach(e => {
          groupItem.userCache[e.user_id] = e.username
        })

        this.tempUser = { ...groupItem, type: 2 }
        this.groupList[groupIndex] = groupItem

        this.notInGroupCheckList = []
        this.GroupMemberPlusVisible = false
      })
    },

    // 加入新群通知
    joinedNewGroupNoti(res) {
      const groupId = res.detail.data
      console.log(`被拉入了群 ${groupId}`)
      // 获取群信息， 添加到groupList数据里
      findGroupUserListById({
        group_id: groupId
      }).then(val => {
        // console.log(val)
        const tmp = val
        const userList = tmp.user_list
        const userCache = {}
        for (let k = 0; k < userList.length; k++) {
          userCache[userList[k].user_id] = userList[k].username
        }
        tmp['userCache'] = userCache
        tmp['isExpand'] = false
        this.groupList.push(tmp)// .splice(0, 0, tmp)
      })
    },

    // 发送。。。。
    sendAction(e) {
      if (e.length === 0) {
        this.$message.error('请输入内容')
        return
      }
      console.log(e)
      for (let i = 0; i < e.length; i++) {
        const item = e[i]
        if (item.type === 1) {
          // 文本
          this.sendMsgContent(item.value)
        } else if (item.type === 2) {
          // 图片文件
          this.sendImage(item.value)
        }
      }
    },

    // 发送图片文件
    sendImage(file) {
      if (this.tempUser) {
        if (this.tempUser.type === 2) {
          // 群组消息
          let selfMsg = sendGroupImageMsg(this.userId, this.tempUser.id, file)
          selfMsg = this.transGroupMsg(selfMsg)
          this.groupMsgList[this.tempUser.id].msgList.push(selfMsg)
        } else if (this.tempUser.type === 1) {
          // 好友消息
          const selfMsg = sendUserImageMsg(this.userId, this.tempUser.user_id, file)
          // 添加消息
          this.msgDataSource[this.tempUser.user_id].msgList.push(selfMsg)
        }
        this.$forceUpdate()
        this.needNexTickCount = this.needNexTickCount + 1
        // this.needNexTick = true
        this.$nextTick(() => {
          this.scrollToBottom()
          // 消息列表 增加消息 重新监听
          this.observeMsgRows()
        })
      }
    },

    // 点击发送消息
    sendMsgContent(msg) {
      // console.log(this.userId)
      if (this.tempUser) {
        if (!msg) {
          this.$message.error('请输入内容')
          return
        }
        if (this.tempUser.type === 2) {
          // 群组消息
          let selfMsg = sendGroupMessage(this.userId, this.tempUser.id, msg)
          selfMsg = this.transGroupMsg(selfMsg)

          this.groupMsgList[this.tempUser.id].msgList.push(selfMsg)
        } else if (this.tempUser.type === 1) {
          // 好友消息
          const selfMsg = sendUserMessage(this.userId, this.tempUser.user_id, msg)

          this.msgDataSource[this.tempUser.user_id].msgList.push(selfMsg)
        }
        this.$forceUpdate()
        // this.needNexTick = true
        this.$nextTick(() => {
          this.scrollToBottom()
          // 消息列表 增加消息 重新监听
          this.observeMsgRows()
        })
      }
    },

    // 点击 发送失败 再次发送
    sendAgainClick(item) {
      sendFailedMessageAgain(item)
    },

    // 点击用户 聊天（打开窗口）
    clickToTalk(item, index) {
      if (this.tempUser && this.tempUser.type === 1 && this.tempUser.user_id === item.user_id) {
        // 已经打开了该窗口
        return
      }
      const msgObj = this.msgDataSource[item.user_id]
      if (!msgObj) {
        const section = {
          info: { ...item },
          msgList: [],
          hasMore: true
        }
        this.msgDataSource[item.user_id] = section
      }
      item['unRead'] = false
      this.tempUser = { ...item, type: 1 }
      this.tempIndex = index
      this.hasMore = this.msgDataSource[item.user_id].hasMore

      // 某个聊天窗口展开时，判断是否需要拉取历史聊天数据
      this.doFetchMessageListWhenOpenChatWindow((isTrue) => {
        this.$nextTick(() => {
          this.scrollToBottom()
          // 重置监听列表
          this.observeMsgRows()
        })
      })
    },

    // 点击群聊
    clickToGroupTalk(item, index) {
      if (this.tempUser && this.tempUser.type === 2 && this.tempUser.id === item.id) {
        // 已经打开了该窗口
        return
      }
      // console.log('点击群聊')
      // console.log(item)
      // console.log(this.groupMsgList)
      const msgObj = this.groupMsgList[item.id]
      if (!msgObj) {
        const section = {
          info: { ...item },
          msgList: [],
          hasMore: true
        }
        this.groupMsgList[item.id] = section
      }
      item['unRead'] = false
      this.tempUser = { ...item, type: 2 }
      this.tempIndex = index
      this.hasMore = this.groupMsgList[item.id].hasMore
      this.doFetchGroupMsgListWhenOpenWindow((isTrue) => {
        this.$nextTick(() => {
          this.scrollToBottom()
          // 重置监听列表
          this.observeMsgRows()
        })
      })
    },

    // ------------------ 群聊判断 是否拉取历史记录
    doFetchGroupMsgListWhenOpenWindow(callback) {
      if (this.tempUser == null) {
        return
      }
      const msgList = this.groupMsgList[this.tempUser.id].msgList
      if (msgList.length >= 20) {
        callback(true)
        return
      }
      // 拉取历史记录
      this.fetchGroupMsgList(callback)
    },

    // ----------------------------- 私聊 ---------------------
    // 判断是否拉取历史记录（在打开聊天窗口时）
    doFetchMessageListWhenOpenChatWindow(callback) {
      if (this.tempUser == null) {
        return
      }
      const msgList = this.msgDataSource[this.tempUser.user_id].msgList
      if (msgList.length >= 20) {
        callback(true)
        return
      }
      // 当聊天数据少于20条时， 去拉一下历史记录数据
      this.fetchMessageWithOther(callback)
    },

    // 监听列表 消息列表、每一个消息 与窗口交叉
    observeMsgRows() {
      // 置空监听的 下标 列表
      this.observeList = []
      if (!this.tempUser) { return }
      const message = document.querySelectorAll('.msgrow')
      const observer = new IntersectionObserver(entries => {
        entries.forEach(ele => {
          this.handleObserver(ele)
        })
      })
      message.forEach(e => observer.observe(e))
    },

    // 监听结果处理
    handleObserver(e) {
      const index = parseInt(e.target.dataset.index)
      if (e.isIntersecting) {
        // 在窗口中
        if (this.observeList.length === 0) {
          this.observeList.push(index)
        } else {
          if (this.observeList[0] > index) { // 比第一个小，放前面
            this.observeList.unshift(index)
          } else if (this.observeList[0] < index) { // 比第一个大，放后面
            this.observeList.push(index)
          }
          // 还有一个相等的、弃掉
        }
        // 判断是否是别人的消息 并且未读，
        // 然后发送已读状态
        this.readObserveMsgAtIndex(index)
      } else {
        // 不在窗口中
        const oIndex = this.observeList.indexOf(index)
        if (oIndex >= 0) {
          this.observeList.splice(oIndex, 1)
        }
      }

      // this.observeList
      this.checkNeedFetchMoreMessage()
      // console.log(this.observeList)
    },

    // 监听状态下的消息 状态 发送为已读
    readObserveMsgAtIndex(index) {
      if (!this.tempUser) {
        return
      }
      if (this.tempUser.type === 2) { // 群消息-无状态
        return
      }
      const msgList = this.msgDataSource[this.tempUser.user_id].msgList
      if (msgList[index].sender_id !== this.userId && msgList[index].status !== 'Read') {
        // 别人发的消息、还没有 已读, 则发送已读
        readMessage(msgList[index].message_id)
        this.msgDataSource[this.tempUser.user_id].msgList[index].status = 'Read'
        this.$forceUpdate()
      }
    },

    // 点击关闭聊天窗口
    closeRoomClick() {
      this.tempUser = null
      this.tempIndex = -1
    },

    // 接收到 消息 发送失败
    getSendFailedMessage(res) {
      const msgItem = res.detail.data
      const toUserId = msgItem.receiver_id
      const msgList = this.msgDataSource[toUserId].msgList
      const theIndex = msgList.findIndex(val => val.unique_id === msgItem.unique_id)
      if (theIndex >= 0) {
        // 找到了该消息
        msgList[theIndex] = msgItem
        this.msgDataSource[toUserId].msgList = msgList
        this.$forceUpdate()
      }
    },

    // 获取消息 接收消息
    getSocketMessage(res) {
      const msg = res.detail.data
      // 发送的消息
      var distId = msg.sender_id
      var theIdGroup = this.msgDataSource[distId]
      if (theIdGroup) {
        if (msg.unique_id.length > 0) {
          const index = theIdGroup.msgList.findIndex(val => val.unique_id === msg.unique_id)
          // console.log('收到消息 unique_id index  ' + index)
          if (index >= 0) {
            theIdGroup.msgList[index] = msg
          } else {
            theIdGroup.msgList.push(msg)
          }
        } else {
          theIdGroup.msgList.push(msg)
        }
        this.msgDataSource[distId] = theIdGroup
      } else {
        const item = this.userList.find(e => e.user_id === distId)
        const section = {
          info: { ...item, type: 1 },
          msgList: [msg],
          hasMore: true
        }
        this.msgDataSource[distId] = section
      }
      // 收到消息，发送阅读状态
      // 如果当前在该 消息的 发送者 窗口，则直接已读
      if (this.tempUser && this.tempUser.user_id === distId) {
        msg.status = 'Read'
        readMessage(msg.message_id)
      } else {
        // 否则，更改为 已接收
        msg.status = 'Received'
        receivedMessage(msg.message_id)
        const index = this.userList.findIndex(val => val.user_id === distId)
        if (index >= 0) {
          this.userList[index]['unRead'] = true
          this.$message.success(`${this.userList[index].username} 来消息啦`)
        }
      }
      this.$forceUpdate()
      if (msg.message_type === 'IMG') {
        this.needNexTickCount = this.needNexTickCount + 1
      }
      this.$nextTick(() => {
        this.scrollToBottom()
        // 收到消息，重新监听
        this.observeMsgRows()
      })
    },

    // 接收到群消息
    getSocketGroupMessage(res) {
      // 给msg添加一个sendname属性
      const msg = this.transGroupMsg(res.detail.data)
      // 某个群id
      var distId = parseInt(msg.receiver_id)

      var theIdGroup = this.groupMsgList[distId]
      if (theIdGroup) {
        if (msg.unique_id.length > 0) {
          const index = theIdGroup.msgList.findIndex(val => val.unique_id === msg.unique_id)
          // console.log('收到群消息 unique_id index  ' + index)
          // console.log(msg)
          if (index >= 0) {
            theIdGroup.msgList[index] = msg
          } else {
            theIdGroup.msgList.push(msg)
          }
        } else {
          theIdGroup.msgList.push(msg)
        }
        this.groupMsgList[distId] = theIdGroup
      } else {
        const item = this.groupList.find(e => e.id === distId)
        const section = {
          info: { ...item, type: 2 },
          msgList: [msg],
          hasMore: true
        }
        this.groupMsgList[distId] = section
      }

      // 收到消息，标记有消息的状态
      if (this.tempUser && this.tempUser.type === 2 && this.tempUser.id === distId) {
        // 该群已经打开
      } else {
        // 该群未打开
        const index = this.groupList.findIndex(val => val.id === distId)
        if (index >= 0) {
          this.groupList[index]['unRead'] = true
        }
        console.log(msg)
        console.log(this.groupList)
      }

      this.$forceUpdate()
      this.$nextTick(() => {
        this.scrollToBottom()
        // 收到消息，重新监听
        this.observeMsgRows()
      })
    },

    // 给群消息增加一个发送者名称
    transGroupMsg(msg) {
      if (this.tempUser && this.tempUser.userCache) {
        msg['sender_name'] = this.tempUser.userCache[msg.sender_id]
      }
      if (msg.sent_at !== undefined && msg.sent_at > 0) {
        msg['sent_at_str'] = dateStrFromTimeStamp(msg.sent_at, 2)
      }
      return msg
    },

    // 收到 消息 状态改变 的消息
    getSocketMessageStatusChange(res) {
      // console.log(res.detail.data)
      // console.log(res.detail.data.type)
      // console.log('----')
      // console.log(res.detail.data.type === 33)
      if (parseInt(res.detail.data.type) === 33) {
        const msg = this.transGroupMsg(res.detail.data)
        console.log(msg)
        const itemObj = this.groupMsgList[msg.receiver_id * 1]
        // console.log(itemObj)
        const msgList = itemObj.msgList
        // console.log(msg)
        const index = msgList.findIndex(val => val.unique_id === msg.unique_id)
        if (index >= 0) {
          msgList[index]['sender_name'] = msg.sender_name
          msgList[index]['sent_at_str'] = msg.sent_at_str
          this.groupMsgList[msg.receiver_id * 1].msgList = msgList
          this.$forceUpdate()
        }
        return // 群消息
      }
      const msg = res.detail.data
      const itemObj = this.msgDataSource[msg.receiver_id]
      if (!itemObj || itemObj === undefined) {
        // console.log('未定义。。。')
        // console.log(this.msgDataSource)
        // console.log(msg)
        // console.log(itemObj)
        // console.log('----------')
        return
      }
      const msgList = this.msgDataSource[msg.receiver_id].msgList
      const index = msgList.findIndex(val => val.unique_id === msg.unique_id)
      if (index >= 0) { // 找到那个消息、赋值消息状态
        msgList[index].status = msg.status
        this.msgDataSource[msg.receiver_id].msgList = msgList
        this.$forceUpdate()
      }
    },

    // 其它用户 上线、下线消息
    getOtherOnline(res) {
      const msgItem = res.detail.data

      const userId = msgItem.sender_id

      const index = this.userList.findIndex(val => val.user_id === userId)

      if (index >= 0) {
        var item = this.userList[index]
        item.status = msgItem.content * 1
        item.last_active_at = msgItem.sent_at
        this.userList[index] = item
        if (item.status === 1) {
          this.$message.success(`用户${item.username}上线了`)
        } else {
          this.$message.error(`用户${item.username}下线了`)
        }
      }
    },

    // 检查是否需要加载更多的历史记录列表
    checkNeedFetchMoreMessage() {
      // 在窗口显示的 元素的 下标列表， 这里判断是否需要加载上一页数据
      if (this.observeList.length > 0 && this.hasMore) {
        const firstIndex = this.observeList[0]
        if (firstIndex <= 10) {
          // 剩余10个元素后开始加载历史记录
          // loadNextMessageListFromMsgId
          // 加载列表后需要重新监听

          const callback = (isTrue) => {
            if (!isTrue) {
              return
            }
            const div = document.getElementById('scroll-page')
            if (div && this.tempUser) {
              const scrollH = div.scrollHeight
              const scrollTop = div.scrollTop
              // 记录刷新前的偏移和位置
              this.tempUser['lastScroll'] = {
                scrollH: scrollH,
                scrollTop: scrollTop
              }
              this.needNexTick = false
              console.log(this.tempUser.lastScroll)
              console.log('初始 --- ')
              this.$forceUpdate()
              // 判断是否
              this.$nextTick(() => {
                const div2 = document.getElementById('scroll-page')
                console.log('div2: h-' + div2.scrollHeight + ' : top-' + div2.scrollTop)
                const nextScrollTop = (div2.scrollHeight - this.tempUser.lastScroll.scrollH) + this.tempUser.lastScroll.scrollTop
                const nextObj = {
                  scrollH: div2.scrollHeight,
                  scrollTop: nextScrollTop
                }
                div2.scrollTop = nextScrollTop

                this.tempUser.lastScroll = nextObj

                // 重置监听列表
                this.observeMsgRows()
                // 加载结束后再次检查判断
                this.checkNeedFetchMoreMessage()
              })
            }
          }
          if (this.tempUser && this.tempUser.type === 2) {
            // 群
            this.fetchGroupMsgList(callback)
          } else {
            this.fetchMessageWithOther(callback)
          }
        }
      }
    },

    // 用户聊天记录
    fetchMessageWithOther(callback) {
      if (this.isLoadingMsg) { // 正在加载中。。
        return
      }

      if (this.tempUser == null) { // 当前没有打开窗口
        callback(false)
        return
      }

      if (this.tempUser.type === 2) {
        return // 群消息
      }

      if (!this.hasMore) { // 没有更多了
        callback(false)
        return
      }

      const user_id = this.tempUser.user_id
      const msgList = this.msgDataSource[user_id].msgList

      var from_id = 0
      if (msgList.length > 0) {
        from_id = msgList[0].message_id
      }

      this.isLoadingMsg = true

      getMessageList({
        user_id: this.tempUser.user_id,
        size: 20,
        from_id: from_id
      }).then(val => {
        // console.log(val)
        const tmpList = val.list
        for (var index = 0; index < tmpList.length; index++) {
          // console.log(index)
          const element = tmpList[index]
          // console.log('聊天记录解密')
          if (element.message_type === 'TEXT') {
            element.content = decryptMsg(element.content, `${element.unique_id}${element.sender_id}`)
          } else if (element.message_type === 'IMG') {
            this.needNexTickCount = this.needNexTickCount + 1
          }
          tmpList[index] = element
        }
        console.log(tmpList)
        this.hasMore = !(tmpList.length < 20)
        this.msgDataSource[user_id]['hasMore'] = this.hasMore
        this.msgDataSource[user_id].msgList = tmpList.concat(msgList)
        this.isLoadingMsg = false

        console.log('强制刷新。。列表')
        console.log(this.msgDataSource)
        callback(true)
      }).catch(() => {
        this.isLoadingMsg = false
        callback(false)
      })
    },

    // 用户列表
    fetchUserList() {
      getWsUserList().then(val => {
        this.userList = val
      })
    },

    // 群历史记录
    fetchGroupMsgList(callback) {
      if (this.isLoadingMsg) { // 正在加载中。。
        return
      }

      if (this.tempUser == null) { // 当前没有打开窗口
        callback(false)
        return
      }

      if (this.tempUser.type === 1) {
        return // 好友消息
      }

      if (!this.hasMore) { // 没有更多了
        callback(false)
        return
      }
      const groupId = this.tempUser.id
      const msgList = this.groupMsgList[groupId].msgList

      var from_id = 0
      if (msgList.length > 0) {
        from_id = msgList[0].message_id
      }

      this.isLoadingMsg = true

      getGroupMsgList({
        group_id: groupId,
        size: 20,
        from_id: from_id
      }).then(val => {
        // console.log(val)
        const tmpList = val.list
        for (var index = 0; index < tmpList.length; index++) {
          // console.log(index)
          const element = this.transGroupMsg(tmpList[index])
          // console.log('聊天记录解密')
          if (element.message_type === 'TEXT') {
            element.content = decryptMsg(element.content, `${element.unique_id}${element.sender_id}`)
          } else if (element.message_type === 'IMG') {
            this.needNexTickCount = this.needNexTickCount + 1
          }
          tmpList[index] = element
        }
        // console.log(tmpList)
        this.hasMore = !(tmpList.length < 20)
        this.groupMsgList[groupId]['hasMore'] = this.hasMore
        this.groupMsgList[groupId].msgList = tmpList.concat(msgList)
        this.isLoadingMsg = false
        // console.log('强制刷新。。列表')
        // console.log(this.msgDataSource)
        callback(true)
      })
    },

    // 群组列表
    fetchGroupList() {
      getChatGroupList().then(val => {
        // console.log(val)
        for (let index = 0; index < val.length; index++) {
          const userList = val[index].user_list
          const userCache = {}
          for (let k = 0; k < userList.length; k++) {
            userCache[userList[k].user_id] = userList[k].username
          }
          val[index]['userCache'] = userCache
          val[index]['isExpand'] = false
        }
        this.groupList = val
      })
    },

    // 请求数据 =
    fetchNotInGroupUserList(group_id) {
      this.notInGroupUserList = []
      getNotInGroupUserList({
        group_id
      }).then(val => {
        this.notInGroupUserList = val
      })
    },

    // 图片加载成功事件
    imgLoaded(e, item) {
      if (!this.tempUser) {
        return
      }

      // 调整当前偏移
      const div = document.getElementById('scroll-page')
      if (!div) { return }
      // 当遇到需要滚动到底部时、加载成功后再次调用、、
      this.needNexTickCount = this.needNexTickCount - 1
      if (this.tempUser.lastScroll) {
        const scrollH = div.scrollHeight
        const nextScrollTop = (div.scrollHeight - this.tempUser.lastScroll.scrollH) + this.tempUser.lastScroll.scrollTop
        const nextObj = {
          scrollH: scrollH,
          scrollTop: nextScrollTop
        }
        div.scrollTop = nextScrollTop
        this.tempUser.lastScroll = nextObj
      }

      if (this.needNexTickCount <= 0) {
        // 最后一个加载结束了、并且需要滚动到最后
        if (this.needNexTick) {
          // 这次不需要设置needNextick
          this.scrollToBottom(false)
        }
        // 重新监听
        this.observeMsgRows()
        this.needNexTick = false
        this.needNexTickCount = 0
      }
    },

    // 滚动到底部
    scrollToBottom(need = true) {
      const div = document.getElementById('scroll-page')
      if (!div) { return }
      this.needNexTick = need
      div.scrollTop = div.scrollHeight
    }
  }
}
</script>
<style lang='scss' scoped>
.chat-page {
  display: flex;
  flex-direction: column;

  .chat-section {
    display: flex;
    flex-direction: row;
  }

  .chat-left {
    flex: 1;
    margin: 5px;
    border: 1px solid #eee;
    padding: 10px;

    .chat-room {

      .room-top {
        display: flex;
        flex-direction: row;
        align-items: center;

        .name {
          margin-left: 20px;
          flex: 1;
        }

        .group-plus {
          margin-left: 20px;
        }
      }

      .room-content {
        height: 300px;
        margin: 30px 20px 20px 20px;
        overflow-y: auto;
        overflow: auto;
        scrollbar-width: none;

        .msg-left {
          flex-direction: row;
          margin-right: 20%;
        }

        .msg-right {
          flex-direction: row-reverse;
          margin-left: 20%;
        }

        .group-msg-right {
          flex-direction: column;
          align-items: flex-end;
        }

        .group-msg-left {
          flex-direction: column;
          align-items: flex-start;
        }

        .msg-center {
          align-items: center;
        }

        .message {
          display: flex;
          margin-top: 30px;

          .talk-pop {
            padding: 10px;
            background-color: #6ff5d8e5;
            word-break: break-all;
            white-space: pre-line;

            .msg-time {
              display: inline-block;
              padding-left: 8px;
              line-height: 12px;
              font-size: 11px;
              color: #666;
            }
          }

          .msg-img {
            max-width: 160px;
          }

          .sender_name {
            font-size: 13px;
            color: #666;
            padding-bottom: 5px;
          }

          .state {
            white-space: nowrap;
            margin: 0 10px;
            padding: 4px;
            font-size: 10px;
            color: #666;
            background-color: #EBEEF5;
          }
        }
      }

      .room-content::-webkit-scrollbar {
        display: none;
      }

      .room-send {
        display: flex;
        flex-direction: row;
        align-items: flex-end;
        border-top: 1px solid #ddd;

        .send-input {
          max-width: 500px;
          flex: 1;
          // border: 1px solid #ddd;
          // border-radius: 10px;
          height: 200px;
        }
      }
    }
  }

  .user-list {
    width: 150px;
    border: 1px solid #eee;

    .group-item {
      display: flex;
      align-items: center;
      // justify-content: center;

      .expand {
        padding: 5px;
      }
    }

    .group-sub-user {
      font-size: 14px;
      line-height: 1.5;
      margin-bottom: 8px;
      // margin-left: 30px;
      text-align: left;
      user-select: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
    }

    .user-item {
      // text-align: center;
      margin-left: 30px;

      .name {
        // width: 100%;

        .unRead {
          display: inline-block;
          vertical-align: middle;
          margin-right: 4px;
          width: 6px;
          height: 6px;
          border-radius: 50%;
          background-color: red;
        }
      }
    }
  }
}

.group-dialog {
  .group-check {
    display: block;
    margin: 0 0 15px 12px;
  }
}
</style>